package demo1;

/**
 * 模拟实现哈希桶*/
public class HashBucket {
    //创建结点
    static class Node{
        public int key;
        public int value;
        public Node next;
        public Node(int key, int value) {
            this.key = key;
            this.value = value;
        }
    }
    //创建哈希桶底层数组、有效元素计数器、荷载因子
    public Node[] array;
    public int usedSize;
    public static final float DEFAULT_LOAD_FACTOR = 0.75f;
    public HashBucket() {
        array =  new Node[10];
    }

    /**
     * hash方法*/
    private int hash(int key) {
        return key%array.length;
    }

    /**
     * 在哈希桶中插入数据*/
    public boolean put(int key, int val) {
        //获取待插入元素的哈希地址，判断是否存在相同key值的元素
        //若是存在，则仅修改value值并return false
        int index = hash(key);
        Node cur = array[index];
        Node prev = null;
        while(cur!=null) {
            if(cur.key==key) {
                cur.value = val;
                return false;
            }
            prev = cur;
            cur = cur.next;
        }
        //若是链表中无相同key值的元素，则将该元素尾插值对应链表后
        //注意：若是链表中无元素时，prev此时为空，故需要对prev进行判空
        Node node = new Node(key,val);
        if(prev!=null) {
            prev.next = node;
        } else {
            array[index] = node;
        }
        this.usedSize++;
        //每插入一个元素均需对其荷载因子进行计算，若是超过，需要对哈希表底层数组进行扩容以降低荷载
        //（注意：不可直接使用copyOf对数组进行扩容，因为在哈希表中的每个元素都是按照hash方法进行分配地址，而hash方法又
        // 依赖于数组长度，故当对数组进行扩容时需要将表中所有元素重新调用hash方法插入）
        if((this.usedSize*1.0f/array.length)>=DEFAULT_LOAD_FACTOR) {
            resize();
        }
        return true;
    }

    //对哈希表底层数组进行扩容
    private void resize() {
        Node[] newArray = new Node[array.length*2];
        for(int i = 0; i < array.length; i++) {
            Node cur = array[i];
            while(cur!=null) {
                Node nextNode = cur.next;

                int newIndex = cur.key% newArray.length;
                cur.next = newArray[newIndex];
                newArray[newIndex] = cur;

                cur = nextNode;
            }
        }
        this.array = newArray;
    }

    /**
     * 在哈希桶中搜索数据*/
    public int get(int key) {
        int index = hash(key);
        Node cur = array[index];
        while(cur!=null) {
            if(cur.key==key) {
                return cur.value;
            }
            cur = cur.next;
        }
        return -1;
    }
}
